﻿using System;
using System.Collections.Generic;
using System.Windows.Forms;

using PcapDotNet.Core;
using PcapDotNet.Packets;
using PcapDotNet.Packets.IpV4;

namespace NetMon
{
    static class Program
    {
        private static PacketDevice _getDevice()
        {
            IList<LivePacketDevice> allDevices = LivePacketDevice.AllLocalMachine;

            if (allDevices.Count == 0)
            {
                MessageBox.Show("WinPcap thinks there are no network devices available :(\n\nMake sure that \"WinPcap\" is installed and running.", "Unable to find network interfaces.", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                Environment.Exit(1);
            }

            // Shortcut to select the only available interface.
            if (allDevices.Count == 1)
            {
                return allDevices[0];
            }

            string[] deviceNames = new string[allDevices.Count];
            for (int i = 0; i < allDevices.Count; ++i)
            {
                deviceNames[i] = allDevices[i].Description;
            }


            PacketDevice selected = null;
            InterfaceSelect dlg = new InterfaceSelect(deviceNames);
            try
            {
                DialogResult result = dlg.ShowDialog();
                if (result == DialogResult.OK)
                    selected = allDevices[dlg.SelectedInterface()];
            }
            finally
            {
                dlg.Dispose();
            }

            return selected;
        }

        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            PacketDevice dev = _getDevice();
            if (dev == null)
                return;

            IpV4Address? myAddr = null;
            foreach (DeviceAddress devAddr in dev.Addresses)
            {
                if (devAddr.Address.Family != SocketAddressFamily.Internet)
                    continue;
                IpV4SocketAddress ipaddr = (IpV4SocketAddress)devAddr.Address;
                myAddr = ipaddr.Address;
            }
            if (myAddr == null)
            {
                MessageBox.Show("The interface you selected does not appear to support the IPv4 network protocol.", "Unsupported network interface.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            using (PacketCommunicator communicator = dev.Open(65536, PacketDeviceOpenAttributes.None, 5))
            {
                if (communicator.DataLink.Kind != DataLinkKind.Ethernet)
                {
                    MessageBox.Show("This tool only supports ethernet network adapters. Please use a different adapter.", "Unsupported network interface type.", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    return;
                }

                // Compile the filter
                using (BerkeleyPacketFilter filter = communicator.CreateFilter(string.Format("(tcp or udp) and dst host {0} and not src host {0}", myAddr.ToString())))
                {
                    // Set the filter
                    communicator.SetFilter(filter);
                    Console.WriteLine("ok");
                }

                Application.Run(new MainWindow(dev.Description, communicator));
            }
        }
    }
}
